home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 1
/
Cream of the Crop 1.iso
/
PROGRAM
/
LDB171.ARJ
/
BINDER.CPP
next >
Wrap
C/C++ Source or Header
|
1992-07-10
|
19KB
|
1,017 lines
/*
binder.cpp -- Loose Data Binder v 1.7
(C) Copyright 1992 John W. Small
All rights reserved
PSW / Power SoftWare
P.O. Box 10072
McLean, Virginia 22102 8072 USA
(703) 759-3838
*/
#include <string.h>
#include <fstream.h>
#include "binder.hpp"
static Binder comPRegistry(BDR_DDELETE);
Binder& Binder::comPv = comPRegistry;
unsigned Binder::comPID(BDRcomP comP)
{
unsigned i = 0;
BDRcomP *CP;
while ((CP = (BDRcomP *)comPv.atGet(i++))
!= (BDRcomP *)0)
if (*CP == comP)
return i;
return 0;
}
BDRcomP Binder::comPLU(unsigned ID)
{
BDRcomP *CP = (BDRcomP *)comPv.atGet(--ID);
return (CP? *CP : BDRcomP0);
}
int Binder::initData(unsigned flags, unsigned maxNodes,
unsigned limit, unsigned delta)
{
curNode = first = nodes = 0;
comP = BDRcomP0;
/*
The following relationships are maintained
during operation of a binder:
1 <= delta <= lowLimit <= limit <= maxNodes
<= BDR_MAXNODES
lowThreshold = lowLimit - delta;
*/
if (maxNodes > BDR_MAXNODES)
maxNodes = BDR_MAXNODES;
if (limit > maxNodes)
limit = maxNodes;
if (delta > limit)
delta = limit;
if (!delta) {
delta = 1;
if (limit < delta)
limit = delta;
if (maxNodes < limit)
maxNodes = limit;
}
if ((linkS = new voiD[limit]) == voiDV0) {
this->limit = lowLimit = lowThreshold
= this->delta = this->maxNodes
= this->flags = 0;
return 0;
}
else {
this->limit = limit;
this->delta = delta;
this->maxNodes = maxNodes;
lowLimit = limit;
lowThreshold = lowLimit - delta;
this->flags = (flags | BDR_SORTED);
return 1;
}
}
void Binder::destruct()
{
if (flags & BDR_DDELETE)
allDel();
else
allRmv();
if (linkS) {
delete linkS;
linkS = voiDV0;
}
}
void Binder::sberror(const char * msg)
{
if (Binder::streamDebug)
cerr << endl << msg << endl;
}
void Binder::berror(const char * msg)
{
if (streamDebug)
cerr << endl << msg << endl;
}
void Binder::store(ostream& os)
{
unsigned i;
os << maxNodes << BDRendm << limit << BDRendm
<< delta << BDRendm << nodes << BDRendm
<< curNode << BDRendm << flags << BDRendm
<< comPID(comP) << BDRendm;
if (!os)
berror("unable to store Binder "
"data on stream");
else for (i = 0; i < nodes; i++)
Dstore(os,atGet(i));
}
BindeR Binder::load(istream& is, BindeR thiS)
{
unsigned maxNodes, limit, delta, nodes;
unsigned curNode, flags, comPid;
unsigned i, newed;
is >> maxNodes >> BDRnextm >> limit >> BDRnextm
>> delta >> BDRnextm >> nodes >> BDRnextm
>> curNode >> BDRnextm >> flags >> BDRnextm
>> comPid >> BDRnextm;
if (!is) {
sberror("unable to load Binder "
"data from stream");
return BindeR0;
}
flags |= BDR_DDELETE;
//reloaded nodes are dynamic!
if (thiS)
newed = 0;
else {
if ((thiS = new Binder(initVFTsOnly))
== BindeR0) {
sberror("unable to construct "
"new Binder for loading");
return BindeR0;
}
newed = 1;
}
if (!thiS->initData(flags,maxNodes,limit,delta)) {
sberror("unable to initialize Binder "
"from reloaded stream data");
if (newed)
delete (voiD) thiS;
return BindeR0;
}
for (i = 0; i < nodes; i++)
(void) thiS->insQ(thiS->Dload(is));
thiS->setCurNode(curNode);
thiS->setComP(comPLU(comPid));
return thiS;
}
int Binder::vload(const char * filename,
BDRsloaD sloaD, voiD thiS)
{
ifstream is(filename);
if (is) {
int ok = ((*sloaD)(is,thiS)? 1 : 0);
if (!ok)
initData(0U,0U,0U,0U);
is.close();
return ok;
}
else {
initData(0U,0U,0U,0U);
berror("unable to load Binder from "
"file ...");
berror(filename);
return 0;
}
}
int Binder::streamDebug = 0;
char Binder::memberTermChar = '\n';
void Binder::RegisterComP(BDRcomP comP)
{
if (comP) if (!comPID(comP)) {
BDRcomP *CP = new BDRcomP;
if (CP) {
*CP = comP;
if (!comPv.insQ(CP))
delete CP;
}
}
}
Binder::Binder(voiDV argv, unsigned argc, unsigned flags)
{
if (initData(flags,BDR_MAXNODES,argc,BDR_DELTA))
if (argv)
if (argc > 0)
while (argc--)
(void) push(argv[argc]);
else
for (argc = 0; insQ(argv[argc]);
argc++)
/* null stmt */;
}
int Binder::save(const char *filename)
{
if (flags & BDR_DSTORE) {
ofstream os(filename);
if (os) {
store(os);
os.close();
return 1;
}
else {
berror("unable to save Binder in "
"file ...");
berror(filename);
}
}
return 0;
}
voiDV Binder::vector()
{
voiDV V = voiDV0;
if (nodes) if ((V = new voiD[nodes+1]) != voiDV0) {
for (unsigned i = 0; i < nodes; i++)
V[i] = atGet(i);
V[i] = voiD0;
}
return V;
}
unsigned Binder::setLimit(unsigned newLimit)
{
voiDV newLinkS;
unsigned i;
if (newLimit < nodes)
newLimit = nodes;
else if (newLimit > maxNodes)
newLimit = maxNodes;
if (newLimit < delta)
newLimit = delta;
if (!linkS || !newLimit || newLimit == limit)
return 0;
if ((newLinkS = new voiD[newLimit]) == voiDV0)
return 0;
if ((i = limit - first) > nodes)
i = nodes;
memcpy(newLinkS,&linkS[first],sizeof(linkS[0])*i);
/* copy wrap around */
if (i < nodes)
memcpy(&newLinkS[i],linkS,
sizeof(linkS[0])*(nodes-i));
if (newLimit > limit)
if (newLimit - delta > limit)
lowLimit = newLimit - delta;
else
lowLimit = limit;
else
if (newLimit - delta > delta)
lowLimit = newLimit - delta;
else
lowLimit = delta;
lowThreshold = lowLimit - delta;
delete linkS;
linkS = newLinkS;
limit = newLimit;
first = 0;
return limit;
}
unsigned Binder::setDelta(unsigned newDelta)
{
return ((newDelta && newDelta <= lowLimit)?
delta = newDelta : 0);
}
unsigned Binder::setMaxNodes(unsigned newMaxNodes)
{
return ((newMaxNodes >= limit)?
(maxNodes = (newMaxNodes
> BDR_MAXNODES)? BDR_MAXNODES
: newMaxNodes) : 0);
}
voiD Binder::atIns(unsigned n, voiD D)
{
voiDV newLinkS;
unsigned newLimit, i;
if (!linkS || !D)
return voiD0;
if (nodes == limit) {
if (limit == maxNodes)
return voiD0;
newLimit = (maxNodes - delta > limit)?
limit + delta : maxNodes;
if ((newLinkS = new voiD[newLimit])
== voiDV0) return voiD0;
if ((i = limit - first) > nodes)
i = nodes;
memcpy(newLinkS,&linkS[first],
sizeof(linkS[0])*i);
/* copy wrap around */
if (i < nodes)
memcpy(&newLinkS[i],linkS,
sizeof(linkS[0])*(nodes-i));
/*
Compute next smaller linkS size
and threshold for shrinking.
*/
lowLimit = limit;
lowThreshold = lowLimit - delta;
/* swap new for old */
delete linkS;
linkS = newLinkS;
limit = newLimit;
first = 0;
}
if (!Dattach(D))
return voiD0;
if (!n) /* push */
linkS[first? --first
: (first = limit - 1)] = D;
else if (n >= nodes) /* insQ */
linkS[(first+(n=nodes))%limit] = D;
else { /* insert interior */
i = (first + n) % limit;
if (i < first || !first)
/* move rear rightward */
memmove(&linkS[i+1],&linkS[i],
sizeof(linkS[0])
* (nodes-n));
else { /* move front leftward */
memmove(&linkS[first-1],&linkS[first],
sizeof(linkS[0])*(n+1));
first--;
}
linkS[i] = D;
}
nodes++;
if (n <= curNode)
curNode++;
flags &= ~BDR_SORTED;
return D;
}
voiD Binder::atInsNew(unsigned n, const voiD D)
{
voiD cD;
if (D && flags & BDR_DNEW)
if ((cD = Dnew(D)) != voiD0)
if (atIns(n,cD))
return cD;
else
Ddelete(cD);
return voiD0;
}
voiD Binder::atRmv(unsigned n)
{
voiDV newLinkS;
unsigned newLimit, i;
voiD D;
if (!linkS || n >= nodes)
return voiD0;
D = linkS[i=(first+n)%limit];
if (!n) { /* pop */
if (++first >= limit)
first = 0;
}
else if (n != nodes-1) { /* del interior */
if (i < first) /* move tail leftward */
memmove(&linkS[i],linkS[i+1],
sizeof(linkS[0])*(nodes-n-1));
else { /* move head rightward */
memmove(&linkS[first+1],&linkS[first],
sizeof(linkS[0])*n);
first++;
}
}
if (--nodes == 0)
flags |= BDR_SORTED;
if (n < curNode)
curNode--;
else if (n == curNode)
curNode = nodes;
if (nodes < lowThreshold) {
newLimit = lowLimit;
if ((newLinkS = new voiD[newLimit])
!= voiDV0) {
if ((i = limit - first) > nodes)
i = nodes;
memcpy(newLinkS,&linkS[first],
sizeof(linkS[0])*i);
/* copy wrap around */
if (i < nodes)
memcpy(&newLinkS[i],linkS,
sizeof(linkS[0])
*(nodes-i));
/*
Compute next smaller linkS
size and threshold for
shrinking.
*/
if (lowLimit - delta > delta)
lowLimit -= delta;
else
lowLimit = delta;
lowThreshold = lowLimit - delta;
/* swap new for old */
delete linkS;
linkS = newLinkS;
limit = newLimit;
first = 0;
}
}
Ddetach(D);
return D;
}
void Binder::allRmv()
{
while (atRmv(0)) /* null stmt */ ;
}
int Binder::atDel(unsigned n)
{
voiD D;
if (flags & BDR_DDELETE)
if ((D = atRmv(n)) != voiD0) {
Ddelete(D);
return 1;
}
return 0;
}
voiD Binder::atDelAsg(unsigned n, voiD D)
{
voiD S;
if (D && flags & BDR_DASSIGN && flags & BDR_DDELETE)
if ((S = atGet(n)) != voiD0)
if (D != S) if (Dassign(D,S)) {
(void) atDel(n);
return D;
}
return voiD0;
}
int Binder::allDel()
{
voiD D;
if (flags & BDR_DDELETE) {
while ((D = atRmv(0)) != voiD0)
Ddelete(D);
return 1;
}
return 0;
}
voiD Binder::atPut(unsigned n, voiD D)
{
if (linkS && D && (n < nodes)) {
voiD& N = linkS[(first+n)%limit];
if (D != N) if (Dattach(D)) {
flags &= ~BDR_SORTED;
Ddetach(N);
if (flags & BDR_DDELETE)
Ddelete(N);
return (N=D);
}
}
return voiD0;
}
voiD Binder::atPutNew(unsigned n, const voiD D)
{
voiD oldD, cD;
if (!D || !(flags & BDR_DNEW))
return voiD0;
if ((oldD = atGet(n)) == voiD0)
return voiD0;
if (oldD == D)
return voiD0;
if ((cD = Dnew(D)) != voiD0)
if (atPut(n,cD))
return cD;
else
Ddelete(cD);
return voiD0;
}
voiD Binder::atPutAsg(unsigned n, const voiD D)
{
voiD oldD;
if (D && flags & BDR_DASSIGN)
if ((oldD = atGet(n)) != voiD0)
if (D != oldD)
return Dassign(oldD,D);
return voiD0;
}
voiD Binder::atGet(unsigned n)
{
return ((linkS && (n < nodes))?
linkS[(first+n)%limit] : voiD0);
}
voiD Binder::atGetAsg(unsigned n, voiD D)
{
voiD N;
if (D && flags & BDR_DASSIGN)
if ((N = atGet(n)) != voiD0)
if (D != N)
return Dassign(D,N);
return voiD0;
}
voiD Binder::atXchg(unsigned n, voiD D)
{
if (linkS && D && (n < nodes))
if (Dattach(D)) {
flags &= ~BDR_SORTED;
voiD& N = linkS[(first+n)%limit];
voiD oldD = N;
N = D;
Ddetach(oldD);
return oldD;
}
return voiD0;
}
unsigned Binder::index(const voiD D)
{
unsigned i;
if (linkS && D)
for (i = 0; i < nodes; i++)
if (D == linkS[(first+i)%limit])
return i;
return BDR_NOTFOUND;
}
int Binder::forEach(BDRapplY B, voiD M, voiD A)
{
unsigned i;
if (!linkS || !B || !nodes)
return 0;
for (i = 0; i < nodes; i++)
(*B)(linkS[(first+i)%limit],M,A);
return 1;
}
unsigned Binder::CurNode()
{
return ((curNode < nodes)?
curNode : BDR_NOTFOUND);
}
int Binder::setCurNode(unsigned n)
{
return ((curNode = ((n > nodes)? nodes : n))
< nodes);
}
voiD Binder::ins(voiD D)
{
if (atIns(curNode+1,D)) {
if (++curNode >= nodes)
curNode = nodes - 1;
return D;
}
return voiD0;
}
voiD Binder::insNew(const voiD D)
{
voiD cD;
if (D && flags & BDR_DNEW)
if ((cD = Dnew(D)) != voiD0)
if (ins(cD))
return cD;
else
Ddelete(cD);
return voiD0;
}
voiD Binder::rmv()
{
voiD D;
unsigned n;
if ((D = atRmv(n=curNode)) != voiD0)
if (n--)
curNode = n;
return D;
}
int Binder::del()
{
voiD D;
if (flags & BDR_DDELETE)
if ((D = rmv()) != voiD0) {
Ddelete(D);
return 1;
}
return 0;
}
voiD Binder::delAsg(voiD D)
{
voiD S;
if (D && flags & BDR_DASSIGN && flags & BDR_DDELETE)
if ((S = atGet(curNode)) != voiD0)
if (D != S) if (Dassign(D,S)) {
(void) del();
return D;
}
return voiD0;
}
voiD Binder::next()
{
if (linkS) {
if (curNode >= nodes)
curNode = 0;
else
curNode++;
if (curNode < nodes)
return linkS[(first+curNode)%limit];
}
return voiD0;
}
voiD Binder::nextAsg(voiD D)
{
unsigned oldCurNode = curNode;
voiD S;
if (D && flags & BDR_DASSIGN)
if ((S = next()) != voiD0) {
if (D != S) if (Dassign(D,S))
return D;
curNode = oldCurNode;
}
return voiD0;
}
voiD Binder::prev()
{
if (linkS) {
if (curNode) {
if (curNode > nodes)
curNode = nodes;
curNode--;
}
else
curNode = nodes;
if (curNode < nodes)
return linkS[(first+curNode)%limit];
}
return voiD0;
}
voiD Binder::prevAsg(voiD D)
{
unsigned oldCurNode = curNode;
voiD S;
if (D && flags & BDR_DASSIGN)
if ((S = prev()) != voiD0) {
if (D != S) if (Dassign(D,S))
return D;
curNode = oldCurNode;
}
return voiD0;
}
voiD Binder::firstThat(BDRdetecT B, voiD M)
{
if (linkS && B && nodes)
for (curNode = 0;
curNode < nodes;
curNode++) {
voiD N = linkS[(first+curNode)
%limit];
if ((*B)(N,M))
return N;
}
return voiD0;
}
voiD Binder::lastThat(BDRdetecT B, voiD M)
{
if (linkS && B && nodes) {
curNode = nodes;
while (curNode--) {
voiD N = linkS[(first+curNode)
%limit];
if ((*B)(N,M))
return N;
}
curNode = nodes;
}
return voiD0;
}
int Binder::sort(BDRcomP comP)
{
unsigned low, mid, high;
unsigned d;
voiD D;
/*
The current node is always reset to undefined
regardless of the outcome of sort.
*/
curNode = nodes;
if (flags & BDR_SORTED) {
if (this->comP == comP || !comP)
return 1;
}
else if (!this->comP && !comP)
return 0;
if (comP) {
this->comP = comP;
flags &= ~BDR_SORTED;
}
if (!nodes)
return (int) (flags |= BDR_SORTED);
if (!linkS)
return 0;
if (first) { /* form contiguous block at front */
d = (first + nodes) % limit;
if (d > first)
memmove(linkS,&linkS[first],
sizeof(linkS[0])*nodes);
else if (d < first)
memmove(&linkS[d],&linkS[first],
sizeof(linkS[0])
*(limit-first));
/* else array is full/contiguous */
first = 0;
}
for (high = d = 1; d < nodes; high = ++d) {
low = 0;
D = linkS[d];
while (low < high) {
mid = low + ((high - low) >> 1);
if ((*this->comP)(D,
linkS[mid]) <= 0)
high = mid;
else
low = mid + 1;
}
if (high < d) {
memmove(&linkS[high+1],&linkS[high],
sizeof(linkS[0])*(d-high));
linkS[high] = D;
}
}
return (int) (flags |= BDR_SORTED);
}
voiD Binder::insSort(voiD D)
{
unsigned low, mid, high;
voiD ok;
/*
The current node is left undefined if
anything fails, otherwise it is set to the
newly inserted node.
*/
curNode = nodes;
if (!linkS || !D || nodes >= maxNodes || !comP)
return voiD0;
if (!(flags & BDR_SORTED))
if (!sort())
return voiD0;
low = 0;
high = nodes;
while (low < high) {
mid = low + ((high - low) >> 1);
if ((*comP)(D,
linkS[(first+mid)%limit]) <= 0)
high = mid;
else
low = mid + 1;
}
if ((ok = atIns(high,D)) != voiD0)
curNode = high;
/* atIns() resets sorted to zero */
flags |= BDR_SORTED;
return ok;
}
voiD Binder::insSortNew(const voiD D)
{
voiD cD;
if (D && flags & BDR_DNEW)
if ((cD = Dnew(D)) != voiD0)
if (insSort(cD))
return cD;
else
Ddelete(cD);
return voiD0;
}
voiD Binder::insUnique(voiD D)
{
if (comP) if (!findFirst(D))
return insSort(D);
curNode = nodes;
return voiD0;
}
voiD Binder::insUniqueNew(const voiD D)
{
if (comP && flags & BDR_DNEW)
if (!findFirst(D))
return insSortNew(D);
curNode = nodes;
return voiD0;
}
voiD Binder::findFirst(const voiD K)
{
unsigned low, mid, high;
voiD D;
/*
The current node is left undefined if
anything fails, otherwise it is set to the
newly found node.
*/
curNode = nodes;
if (!linkS || !K || !comP || !nodes)
return voiD0;
if (flags & BDR_SORTED) {
low = 0;
high = nodes;
while (low < high) {
mid = low + ((high - low) >> 1);
if ((*comP)(K,linkS[(first+mid)
%limit]) <= 0)
high = mid;
else
low = mid + 1;
}
if (high < nodes)
if (!(*comP)(K,D=linkS[(first+
high)%limit])) {
curNode = high;
return D;
}
}
else { /* linear search! */
while ((D = next()) != voiD0)
if (!(*comP)(K,D))
return D;
}
return voiD0;
}
voiD Binder::findNext(const voiD K)
{
/*
For sorted binders you must first call findFirst()
to insure consistent results!
*/
voiD D;
/*
The current node is left undefined if
anything fails, otherwise it is set to the
newly found node.
*/
if (!linkS || !K || !comP) {
curNode = nodes;
return voiD0;
}
while ((D = next()) != voiD0)
if (!(*comP)(K,D))
return D;
else if (flags & BDR_SORTED) {
curNode = nodes;
break; /* Look no further! */
}
return voiD0;
}
voiD Binder::findLast(const voiD K)
{
unsigned low, mid, high;
voiD D;
/*
The current node is left undefined if
anything fails, otherwise it is set to the
newly found node.
*/
curNode = nodes;
if (!linkS || !K || !comP || !nodes)
return voiD0;
if (flags & BDR_SORTED) {
low = 0;
high = nodes;
while (low < high) {
mid = low + ((high - low) >> 1);
if ((*comP)(K,linkS[(first+mid)
%limit]) < 0)
high = mid;
else
low = mid + 1;
}
if (high < nodes)
if (!(*comP)(K,D=linkS[(first+
high)%limit])) {
curNode = high;
return D;
}
}
else { /* linear search! */
while ((D = prev()) != voiD0)
if (!(*comP)(K,D))
return D;
}
return voiD0;
}
voiD Binder::findPrev(const voiD K)
{
/*
For sorted binders you must first call findLast()
to insure consistent results!
*/
voiD D;
/*
The current node is left undefined if
anything fails, otherwise it is set to the
newly found node.
*/
if (!linkS || !K || !comP) {
curNode = nodes;
return voiD0;
}
while ((D = prev()) != voiD0)
if (!(*comP)(K,D))
return D;
else if (flags & BDR_SORTED) {
curNode = nodes;
break; /* Look no further! */
}
return voiD0;
}
unsigned Binder::findAll(const voiD K)
{
unsigned count = 0;
/* The current node is left undefined. */
if (findFirst(K))
do {
count++;
} while (findNext(K));
return count;
}
ostream& BDRendm(ostream& os)
{
return os << Binder::memberTermChar << flush;
}
istream& BDRnextm(istream& is)
{
is.get();
return is;
}